package com.ly.nethub.netty.tcp

import android.os.SystemClock
import com.ly.nethub.state.AppStateObserver
import com.ly.nethub.task.BaseTask
import com.ly.nethub.utils.LogUtils
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlin.math.abs

internal class TcpHeartbeatHandler(private val netHub: TcpNetHub) : AppStateObserver {

    private val now get() = SystemClock.elapsedRealtime()

    private var mLastUpdateTime = 0L

    private var mIsForeground = true

    private var mLastPostTime = 0L

    private var mHeartbeatJob: Job? = null

    override fun onBackground() {
        mIsForeground = false
    }

    override fun onForeground() {
        mIsForeground = true
    }

    /**
     * 更新心跳响应时间
     */
    fun updateTime() {
        mLastUpdateTime = now
    }

    fun start() {
        netHub.apply {
            mHeartbeatJob?.cancel()
            mHeartbeatJob = coroutineFactory.enqueueWorkTask {
                val time = netHub.heartbeatFactory.interruptionTime
                while (true) {
                    if (mLastUpdateTime > 0L) {
                        if (abs(mLastUpdateTime - mLastPostTime) >= time) {
                            LogUtils.d("$TAG 心跳响应间隔时间超过设置的断开时间，开始断开时间")
                            netHub.disconnect(reconnect = true)
                            mLastUpdateTime = -1L
                            mLastPostTime = -1L
                            break
                        }
                    } else {
                        updateTime()
                        LogUtils.d("$TAG 连接首次心跳")
                    }
                    LogUtils.d("$TAG 创建心跳任务,${abs(mLastUpdateTime - mLastPostTime)}")
                    val heartbeat = createHeartbeat()
                    mLastPostTime = now
                    val interval = if (mIsForeground) {
                        netHubOptions.foregroundHeartbeatInterval
                    } else {
                        netHubOptions.backgroundHeartbeatInterval
                    }
                    LogUtils.d("$TAG 心跳延迟 $interval ms")
                    if (!mIsForeground) {
                        LogUtils.d("$TAG 后台心跳:${heartbeat.taskId}")
                    }
                    netHub.sendTask(heartbeat)
                    delay(interval)

                }
            }
        }
    }

    fun stop() {
        LogUtils.d("$TAG 停止心跳任务")
        mHeartbeatJob?.cancel()
        mHeartbeatJob = null
    }

    private fun createHeartbeat(): BaseTask = netHub.heartbeatFactory.create().let {
        if (!it.isHeartbeat) {
            throw IllegalStateException("HeartbeatFactory.create isHeartbeat != true")
        }
        it
    }

    companion object {
        const val TAG = "Heartbeat"
    }
}